function isObject(obj) {
  return typeof obj === 'object' && obj !== null
}
function reactive(obj) {
  return new  Proxy(obj, {
    get(target, key) {
      const res = Reflect.get(target, key)
      // console.log('get', res);
      track(target, key) // 依赖收集
      return isObject(res)? reactive(res) : res
    },
    set(target, key, val) {
      const res = Reflect.set(target, key, val) 
      // console.log('set', res);
      trigger(target, key)// 更新
      return res
    },
    deleteProperty(target, key) {
      const res = Reflect.deleteProperty(target, key)
      // console.log('delete', res);
      trigger(target, key)
      return res
    }
  })
}

// 副作用函数
const effectStack = []
function effect(fn) {
  const e = createReactiveEffect(fn)
  e()
  return e
}

function createReactiveEffect(fn) {
  const effect = function(...args) {
    try {
      // 入栈
      effectStack.push(effect)
      // 执行 触发get
      return fn(...args)
    } finally {
      // 出栈
      effectStack.pop()
    }
  }
  return effect
}

// 存放依赖关系
const targetMap = new WeakMap()
 // 依赖收集
function track(target, key) {
  // 取出副作用
  const effect = effectStack[effectStack.length-1]
  if(effect) {
    let depMap =  targetMap.get(target)
    if(!depMap) {
      depMap = new Map()
      targetMap.set(target, depMap)
    }
    // 获取key对于副作用函数set
    let deps = depMap.get(key)
    if(!deps) {
      deps = new Set()
      depMap.set(key, deps)
    }
    // 将副作用添加到deps
    deps.add(effect)
  }
}
 // 触发更新
function trigger(target, key) {
  let depMap =  targetMap.get(target)
  if(!depMap) return
  let deps = depMap.get(key)
  if(deps) {
    deps.forEach(dep => dep());
  }
}

let obj = reactive({
  a: 1,
  b: {
    e: 2
  }
})

effect(() => {
  let el = document.querySelector('#app')
  let node = document.createElement('div')
  node.textContent = obj.a
  el.appendChild(node)
})

setTimeout(() => {
  obj.a = 3000
},1500)

